#!/bin/bash

# Copyright (c) 2010 John M. Woo
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.



VERSION_CURRY=0.37.9-beta
usage()
{
    echo "C/C++ urry"
    echo " - Domain specific langauge for C/C++ make projects"
    echo ""
    echo "Usage:"
    echo "  curry [ -init | -vars | -rules | -reinit | -destroy ]"
    echo ""
    echo " -init    - To be run to initialize your project"
    echo " -vars    - Typically not run by a human"
    echo " -rules   - Typically not run by a human"
    echo " -reinit - Used by developers of curry: Save the current uservars.Makefile,"
    echo "            and regenerate curry"
    echo " -destroy - Used by developers of curry: Remove curry files in current dir"
}
if [ $# -eq 0 ]; then
    usage
    exit 0
fi
VARS=0
RULES=0
INIT=0
DESTROY=0
VERSION=0
REINIT=0
if [ x$1 == x"-vars" ]; then
    VARS=1
fi
if [ x$1 == x"-rules" ]; then
    RULES=1
fi
if [ x$1 == x"-init" ]; then
    INIT=1
fi
if [ x$1 == x"-destroy" ]; then
    DESTROY=1
fi
if [ x$1 == x"-reinit" ]; then
    REINIT=1
fi
if [ x$1 == x"-version" ]; then
    VERSION=1
fi

shift


MAINMAKEFILE=Makefile
USERVARSMAKEFILE=uservars.Makefile
UTILSMAKEFILE=.utils.Makefile
LOOKUPMAKEFILE=.lookup.Makefile
COREMAKEFILE=.core.Makefile

# This generic function checks to see if this specific rule
# has been defined.. If it has.. then, we'll use that one.
# if not. just use the defaulted one.
setup_GENERIC_DEFAULT()
{
    SPECIFIC=$1
    DEFAULT=$2
#    echo "setup_GENERIC_DEFAULT CALLED 1 is $1, 2 is $2" >>/tmp/valuepairs
    if [ x"$SPECIFIC" == x"" ]; then
	echo "#$1 not detected (using default)" 
	SP_RESULT=$DEFAULT
    elif [ x"$SPECIFIC" == x"nil" ]; then
	echo "#$1 detected as nil (use empty)"
	SP_RESULT=
    else
	SP_RESULT=$SPECIFIC
    fi
}
setup_GENERIC_DEFAULT_NO_DEREF()
{
    SPECIFIC_PTR=$1
    SPECIFIC_DEREF=$2
    DEFAULT_PTR=$3
    if [ x"$SPECIFIC_DEREF" == x"" ]; then
	echo "#$1 not detected (using default)" 
	SP_RESULT=$DEFAULT_PTR
    elif [ x"$SPECIFIC_DEREF" == x"nil" ]; then
	echo "#$1 detected as nil (empty)"
	SP_RESULT=
    else
	SP_RESULT=$SPECIFIC_PTR
    fi
}

lookupAssign()
{
    VALUEPAIRS=$1
    name=$2
    var=`echo "${VALUEPAIRS}" |sed "s/.*${name}=\"\([^=]*\)\".*/\1/g"`
    echo "${var}"
}

#setup_SOURCES_OBJDIR_SOURCESUFFIXES()
setup_SOURCES_OBJDIR_SOURCESUFFIXES_TARGETS_E()
{
    VALUEPAIRS=`make -s lookupvars V="SOURCES_$1\ OBJDIR_${1}\ OBJDIR_default\ SOURCESUFFIXES_${1}\ SOURCESUFFIXES_default\ EXEC_${1}"`
    SOURCES=`lookupAssign "${VALUEPAIRS}" SOURCES_$1`
    OBJDIR_S=`lookupAssign "${VALUEPAIRS}" OBJDIR_${1}`
    OBJDIR_D=`lookupAssign "${VALUEPAIRS}" OBJDIR_default`"/"${COMPOSITE}
    setup_GENERIC_DEFAULT "$OBJDIR_S" "$OBJDIR_D"
    OBJDIR=$SP_RESULT

    SOURCESUFFIXES_S=`lookupAssign "${VALUEPAIRS}" SOURCESUFFIXES_${1}`
    SOURCESUFFIXES_D=`lookupAssign "${VALUEPAIRS}" SOURCESUFFIXES_default`
    setup_GENERIC_DEFAULT  "$SOURCESUFFIXES_S" "$SOURCESUFFIXES_D"
    SOURCESUFFIXES=$SP_RESULT

    TARGETS_E=`lookupAssign "${VALUEPAIRS}" EXEC_${1}`
}

setup_SOURCES_OBJDIR_SOURCESUFFIXES_CXX_AR_CXXFLAGS_LDFLAGS_INCFLAGS_TARGETS_EDS()
{
    VALUEPAIRS=`make -s lookupvars V="SOURCES_$1\ OBJDIR_${1}\ OBJDIR_default\ SOURCESUFFIXES_${1}\ SOURCESUFFIXES_default\ CXX_${1}\ AR_${1}\ CXXFLAGS_${1}\ CXXFLAGS_default\ LDFLAGS_${1}\ LDFLAGS_default\ INCFLAGS_${1}\ INCFLAGS_default\ EXEC_${1}\ DLIB_${1}\ SLIB_${1}"`
    SOURCES=`lookupAssign "${VALUEPAIRS}" SOURCES_$1`
    OBJDIR_S=`lookupAssign "${VALUEPAIRS}" OBJDIR_${1}`
    OBJDIR_D=`lookupAssign "${VALUEPAIRS}" OBJDIR_default`"/"${COMPOSITE}
    setup_GENERIC_DEFAULT "$OBJDIR_S" "$OBJDIR_D"
    OBJDIR=$SP_RESULT

    SOURCESUFFIXES_S=`lookupAssign "${VALUEPAIRS}" SOURCESUFFIXES_${1}`
    SOURCESUFFIXES_D=`lookupAssign "${VALUEPAIRS}" SOURCESUFFIXES_default`
    setup_GENERIC_DEFAULT  "$SOURCESUFFIXES_S" "$SOURCESUFFIXES_D"
    SOURCESUFFIXES=$SP_RESULT

    CXX_S=`lookupAssign "${VALUEPAIRS}" CXX_${1}`
    setup_GENERIC_DEFAULT_NO_DEREF "CXX_${1}" "${CXX_S}" "CXX"
    CXX=$SP_RESULT

    AR_S=`lookupAssign "${VALUEPAIRS}" AR_${1}`
    setup_GENERIC_DEFAULT_NO_DEREF "AR_${1}" "${AR_S}" "AR"
    AR=$SP_RESULT

    CXXFLAGS_S=`lookupAssign "${VALUEPAIRS}" CXXFLAGS_${1}`
    CXXFLAGS_D=`lookupAssign "${VALUEPAIRS}" CXXFLAGS_default`
    setup_GENERIC_DEFAULT_NO_DEREF "CXXFLAGS_${1}" "${CXXFLAGS_S}" "CXXFLAGS_default"
    CXXFLAGS=$SP_RESULT
    
    LDFLAGS_S=`lookupAssign "${VALUEPAIRS}" LDFLAGS_${1}`
    LDFLAGS_D=`lookupAssign "${VALUEPAIRS}" LDFLAGS_default`
    setup_GENERIC_DEFAULT_NO_DEREF "LDFLAGS_${1}" "${LDFLAGS_S}" "LDFLAGS_default"
    LDFLAGS=$SP_RESULT

    INCFLAGS_S=`lookupAssign "${VALUEPAIRS}" INCFLAGS_${1}`
    INCFLAGS_D=`lookupAssign "${VALUEPAIRS}" INCFLAGS_default`
    setup_GENERIC_DEFAULT_NO_DEREF "INCFLAGS_${1}" "${INCFLAGS_S}" "INCFLAGS_default"
    INCFLAGS=$SP_RESULT
    
    TARGETS_E=`lookupAssign "${VALUEPAIRS}" EXEC_${1}`
    TARGETS_D=`lookupAssign "${VALUEPAIRS}" DLIB_${1}`
    TARGETS_S=`lookupAssign "${VALUEPAIRS}" SLIB_${1}`

#    VPAIRSOUT=/tmp/valuepairs
#    echo "OBJDIR=${OBJDIR}" >> ${VPAIRSOUT}
#   echo "SOURCESUFFIXES=${SOURCESUFFIXES}" >> ${VPAIRSOUT}
#    echo "CXX=${CXX}" >> ${VPAIRSOUT}
#    echo "AR=${AR}" >> ${VPAIRSOUT}
#    echo "CXXFLAGS=${CXXFLAGS}" >> ${VPAIRSOUT}
#    echo "LDFLAGS=${LDFLAGS}" >> ${VPAIRSOUT}
#    echo "INCFLAGS=${INCFLAGS}" >> ${VPAIRSOUT}

}


setup_DEPS()
{
    DEPS=.deps_d.$1
}

gen_TARGET_rules()
{
    COMPOSITE=$1

#    TARGETS_E=`make -s lookupvar V=EXEC_${COMPOSITE}`
    if [ x${TARGETS_E} != x"" ]; then
	#99% sure the next two lines are unused..
	echo -e "${TARGETS_E}_target: \$(preEXEC_${COMPOSITE}) \$(DEPS_${COMPOSITE}) ${TARGETS_E} \$(postEXEC_${COMPOSITE})"
	echo -e "\t@echo \"\$@, Done\""
	echo -e "${TARGETS_E}: \$(OBJS_${COMPOSITE}) \$(LOCAL_EXEC_DEPS_${COMPOSITE}) \$(EXTERNAL_EXEC_DEPS_${COMPOSITE})"
	echo -e "\t\$(${CXX}) -o \$@ \$(OBJS_${COMPOSITE}) \$(${LDFLAGS})"
    fi
#    TARGETS_D=`make -s lookupvar V=DLIB_${COMPOSITE}`
    if [ x${TARGETS_D} != x"" ]; then
	echo -e "${TARGETS_D}_target: \$(preDLIB_${COMPOSITE}) \$(DEPS_${COMPOSITE}) ${TARGETS_D} \$(postDLIB_${COMPOSITE})"
	echo -e "\t@echo \"\$@, Done\""

	echo -e "${TARGETS_D}: \$(OBJS_${COMPOSITE})"
	echo -e "\t\$(${CXX}) -shared -o \$@ \$(OBJS_${COMPOSITE})"
    fi
#    TARGETS_S=`make -s lookupvar V=SLIB_${COMPOSITE}`
    if [ x${TARGETS_S} != x"" ]; then
	echo -e "${TARGETS_S}_target: \$(preSLIB_${COMPOSITE}) \$(DEPS_${COMPOSITE}) ${TARGETS_S} \$(postSLIB_${COMPOSITE})"
	echo -e "\t@echo \"\$@, Done\""

	echo -e "${TARGETS_S}: \$(OBJS_${COMPOSITE})"
	echo -e "\t\$(${AR}) rcs \$@ \$(OBJS_${COMPOSITE})"
    fi
    echo -e "\$(DEPS_${COMPOSITE}): \$(SOURCES_${COMPOSITE})"
    echo -e "\t@echo \"Generating Dependencies for ${COMPOSITE}\""
    echo -e "\t\$(${CXX}) -MM \$(${CXXFLAGS}) \$(${INCFLAGS}) \$^ > \$(DEPS_${COMPOSITE})"
    echo -e "\t@cat \$(DEPS_${COMPOSITE}) | sed 's/^\(.*\)\.o\(.*\)/\$\$\\(OBJDIR_${COMPOSITE}\\)\/\1\.o\2/g' > /tmp/.deptmp"
    echo -e "\t@mv /tmp/.deptmp \$(DEPS_${COMPOSITE})"
    echo -e ""
    echo -e "-include \$(DEPS_${COMPOSITE})"

}



gen_EXEC_DEPS_vars()
{
    COMPOSITE=$1
#    TARGETS_E=`make -s lookupvar V=EXEC_${COMPOSITE}`
#    echo "targets e is: ${TARGETS_E}" >> /tmp/debugcurry
    #Turning profiling on is super rough.. and only works in this area..
    # To turn profilingon, remove -- )" # -- from each of lines that have this.
    # then use l1api/helplookup.sh to view the time of each and how long it took from
    # the last time we took jiffies
    #PROFILING=";cat /proc/schedstat |grep timestamp >/tmp/profiling/"
    if [ x${TARGETS_E} != x"" ]; then
	echo "LD_DIRS_${COMPOSITE}:=\$(shell echo \$(LDFLAGS_${COMPOSITE}) | sed -e 's/-l[^ ]*//g' -e 's/\-L//g')" #${PROFILING}/LD_DIRS_${COMPOSITE}; )"
	echo "LD_LIBS_${COMPOSITE}:=\$(shell echo \$(LDFLAGS_${COMPOSITE}) | sed -e 's/-L[^ ]*//g' -e 's/\-l/lib/g')" #${PROFILING}/LD_LIBS_${COMPOSITE};)"
	echo "PLIBS_${COMPOSITE}:=\$(shell for dir in \$(LD_DIRS_${COMPOSITE}); do \\"
	echo "for lib in \$(LD_LIBS_${COMPOSITE}); do \\"
	echo "echo \"\$\${dir}/\$\${lib}.a \$\${dir}/\$\${lib}.so\"; \\"
	echo "if [ x\"\$\${dir}\" == x\".\" ]; then \\"
	echo "echo \"\$\${lib}.a \$\${lib}.so\"; \\"
	echo "fi\\"
	echo "done\\"
	echo "done)" #${PROFILING}PLIBS_${COMPOSITE})"
	#I found that evaluating LOCAL_EXEC_DEPS was taking about 250 jiffies (given a project with 3 internal
        #   target libs, and 4 executables)
	#   after the performance mod, 250 went down to 29 :)
        #   The algorithm could be optimized further, but I'll take a minor win for now
	echo "LOCAL_EXEC_DEPS_${COMPOSITE}:=\$(shell for internaltarget in \$(ALLTARGETS_LIBS); do\\"
	echo "for lib in \$(PLIBS_${COMPOSITE}); do \\"
	echo "echo \"\$\${internaltarget}\" | grep -x \"\$\${lib}\" > /dev/null; \\"
	echo "if [ \$\$? -eq 0 ]; then \\"
	echo "echo \"\$\${internaltarget}\"; \\"
	echo "break; \\"
	echo "fi\\"
	echo "done; \\"
	echo "done)" #${PROFILING}LOCAL_EXEC_DEPS_${COMPOSITE};)"
	echo "LOCAL_EDPNODIR_${COMPOSITE}:=\$(shell for dirlib in \$(LOCAL_EXEC_DEPS_${COMPOSITE}); do\\"
	echo "echo \"\`basename \$\${dirlib}\`\"; \\"
	echo "done)" #${PROFILING}LOCAL_EDPNODIR_${COMPOSITE})"
	echo "EXTERNAL_EXEC_DEPLIBS_${COMPOSITE}:=\$(shell for lib in \$(LD_LIBS_${COMPOSITE}); do \\"
	echo "echo \$(LOCAL_EDPNODIR_${COMPOSITE}) |grep \"\$\${lib}\" > /dev/null ;\\"
	echo "if [ \$\$? -ne 0 ]; then \\"
	echo "echo \"\$\${lib}\"; \\"
	echo "fi \\"
	echo "done)" #${PROFILING}EXTERNAL_EXEC_DEPLIBS_${COMPOSITE})"
	echo "EXTERNAL_EXEC_DEPS_${COMPOSITE}:=\$(shell for dir in \$(LD_DIRS_${COMPOSITE}); do \\"
	echo "for lib in \$(EXTERNAL_EXEC_DEPLIBS_${COMPOSITE}); do \\"
	echo "if [ -f \$\${dir}/\$\${lib}.so ]; then \\"
	echo "echo \"\$\${dir}/\$\${lib}.so\"; \\"
	echo "continue;\\"
	echo "fi;\\"
	echo "if [ -f \$\${dir}/\$\${lib}.a ]; then \\"
	echo "echo \"\$\${dir}/\$\${lib}.a\"; \\"
	echo "continue;\\"
	echo "fi;\\"
	echo "done\\"
	echo "done)" #${PROFILING}EXTERNAL_EXEC_DEPS_${COMPOSITE})"

    fi
}

if [ $VARS -eq 1 ]; then
    echo "SHELL=/bin/bash"
    while [ x$1 != x"" ]; do
	echo ""
	COMPOSITE=$1

	setup_SOURCES_OBJDIR_SOURCESUFFIXES_TARGETS_E ${COMPOSITE}
	setup_DEPS $COMPOSITE

	echo "#For the composite \"$COMPOSITE\" ,Sources are: $SOURCES"
	echo "OBJDIR_$COMPOSITE=${OBJDIR}"
	echo "DEPS_${COMPOSITE}=${DEPS}"
	echo "NDSOURCES_$COMPOSITE=\$(notdir \$(SOURCES_$COMPOSITE))"
	echo "EXECDIR_$COMPOSITE=\$(dir \$(EXEC_$COMPOSITE))"
	echo "SLIBDIR_$COMPOSITE=\$(dir \$(SLIB_$COMPOSITE))"
	echo "DLIBDIR_$COMPOSITE=\$(dir \$(DLIB_$COMPOSITE))"
	for sfx in ${SOURCESUFFIXES}; do
	    echo "OBJS_${COMPOSITE}+=\$(filter %.o, \$(NDSOURCES_$COMPOSITE:%${sfx}=${OBJDIR}/%.o))"
	done
	gen_EXEC_DEPS_vars $COMPOSITE
	shift

    done
    echo -e "TEMPOUTPUTDIRS=\$(foreach comp,\$(COMPOSITES),\$(DLIBDIR_\$(comp)) \$(SLIBDIR_\$(comp)) \$(EXECDIR_\$(comp)) \$(OBJDIR_\$(comp)))"
    echo -e "ALLOUTPUTDIRS=\$(shell for dir in \$(TEMPOUTPUTDIRS); do\\"
    echo -e "echo \$\${appended} | grep -w \$\${dir} > /dev/null;\\"
    echo -e "if [ \$\$? -ne 0 ]; then \\"
    echo -e "temp=\"\$\${appended} \$\${dir}\";\\"
    echo -e "appended=\$\${temp};\\"
    echo -e "fi\\"
    echo -e "done;\\"
    echo -e "echo \$\${appended};)"
fi

if [ $RULES -eq 1 ]; then
    while [ x$1 != x"" ]; do
	echo ""
	COMPOSITE=$1
	echo "###################################"
#	setup_SOURCES_OBJDIR_SOURCESUFFIXES_CXX_AR_CXXFLAGS_LDFLAGS_INCFLAGS ${COMPOSITE}
	setup_SOURCES_OBJDIR_SOURCESUFFIXES_CXX_AR_CXXFLAGS_LDFLAGS_INCFLAGS_TARGETS_EDS ${COMPOSITE}
	setup_DEPS $COMPOSITE
	echo "#Main Rule:"
	gen_TARGET_rules  $COMPOSITE

	echo "#Rules for generating objects for $COMPOSITE"
	for file in ${SOURCES}; do
	    echo -e "${OBJDIR}/`basename $file |sed 's/\(.*\)\..*/\1\.o/'`: $file"
	    echo -e "\t\$(${CXX}) \$(${CXXFLAGS}) \$(${INCFLAGS}) -o \$@ -c \$<"
	done
	shift
    done
    echo -e "\$(ALLOUTPUTDIRS):"
    echo -e "\tmkdir -p \$@"
fi

remove()
{
    FILE=$1
    if [ -f $FILE ]; then
	rm -f $FILE
	if [ $? -ne 0 ]; then
	    echo "Failed to remove $FILE"
	else
	    echo "Removed $FILE"
	fi
    fi
}



doCURRY_DESTROY(){
    remove $MAINMAKEFILE
    remove $USERVARSMAKEFILE
    remove $UTILSMAKEFILE
    remove $LOOKUPMAKEFILE
    remove $COREMAKEFILE
    remove .rules
    remove .vars
    rm -f .deps_d.*
    echo "Removed .deps_d.*"
}

begin_uservars()
{
    echo -e "$1" > ${USERVARSMAKEFILE}
    chmod 755 ${USERVARSMAKEFILE}
}
append_uservars()
{
    echo -e "$1" >> ${USERVARSMAKEFILE}
}
begin_coremake()
{
    echo -e $1 > ${COREMAKEFILE}
}
append_coremake()
{
    echo -e $1 >> ${COREMAKEFILE}
}
begin_utilsmake()
{
    echo -e $1 > ${UTILSMAKEFILE}
}
append_utilsmake()
{
    echo -e $1 >> ${UTILSMAKEFILE}
}
begin_lookupmake()
{
    echo -e $1 > ${LOOKUPMAKEFILE}
}
append_lookupmake()
{
    echo -e $1 >> ${LOOKUPMAKEFILE}
}
begin_mainmake()
{
    echo -e $1 > ${MAINMAKEFILE}
    chmod 755 ${MAINMAKEFILE}
}
append_mainmake()
{
    echo -e $1 >> ${MAINMAKEFILE}
}

checkbefore_init()
{
    ERROR=0
    if [ -f ${USERVARSMAKEFILE} ]; then
	echo "Error(File Exists): '${USERVARSMAKEFILE}'"
	ERROR=1
    fi
#    if [ -f ${COREMAKEFILE} ]; then
#	echo "ERROR: File Exists: ${COREMAKEFILE}"
#	ERROR=1
#    fi
#    if [ -f ${UTILSMAKEFILE} ]; then
#	echo "ERROR: File Exists: ${UTILSMAKEFILE}"
#	ERROR=1
#    fi
    return ${ERROR}
}





doCURRY_INIT(){
    echo "Initializing sample files...."
    checkbefore_init
    RET=$?
    if [ $RET -ne 0 ]; then
	echo "..exiting"
	exit 1
    fi
    INPUTFILELIST=$*
    DATENOW=`date`
    WHOAMI=`whoami`
    begin_uservars  "#Sample curry uservars file, Modify me please!"
    append_uservars "#Generated by ${WHOAMI} at ${DATENOW} with curry-${VERSION_CURRY}"
    append_uservars ""
    append_uservars "# The variable \"E\" defines the composite that should be used"
    append_uservars "# when using \"make run\""
    append_uservars "E=c1" 
    append_uservars ""
    if [ x"$INPUTFILELIST" == x"" ]; then
	append_uservars "  SOURCES_c1=main.cpp" 
    else
	append_uservars "  SOURCES_c1=$INPUTFILELIST"
    fi
    append_uservars "     EXEC_c1=mainexec"
    append_uservars "#INCFLAGS_c1=-I."
    append_uservars "#CXXFLAGS_c1=-O2"
    append_uservars "# LDFLAGS_c1=-L. -lexample"
    append_uservars "#  OBJDIR_c1=c1objs"
    append_uservars "#     CXX_c1=powerpc-440-linux-gnu-g++"
    append_uservars "#      AR_c1=powerpc-440-linux-gnu-ar"
    append_uservars "# preEXEC_c1="
    append_uservars "#postEXEC_c1="
    append_uservars ""
    append_uservars "# SOURCES_c2=example.cpp"
    append_uservars "#    DLIB_c2=libexample.so"
    append_uservars "#    SLIB_c2=libexample.a"
    append_uservars "#INCFLAGS_c2=-I../include"
    append_uservars "#CXXFLAGS_c2=-O2"
    append_uservars "#  OBJDIR_c2=exampleobjs"
    append_uservars "#     CXX_c2=powerpc-440-linux-gnu-g++"
    append_uservars "#      AR_c2=powerpc-440-linux-gnu-ar"
    append_uservars "# preDLIB_c2="
    append_uservars "#postDLIB_c2="
    append_uservars ""
    append_uservars ""
    append_uservars "# List the composites that you want to be generated"
    append_uservars "COMPOSITES=c1"
    append_uservars "#COMPOSITES=c2 c1"
    append_uservars ""
    append_uservars ""
    append_uservars "# \"*_default\" vars allow you to define default values if"
    append_uservars "# there isn't a specific one defined. Examples:"
    append_uservars "#CXXFLAGS_default=-O2"
    append_uservars "OBJDIR_default=objs"
    append_uservars "SOURCESUFFIXES_default=.cpp .cxx .c .cc"
    append_uservars ""
    append_uservars ""
    append_uservars "# For those who need to cross compile, you're welcomed to"
    append_uservars "# override the built in variables CXX and AR, or do it with"
    append_uservars "# specific rules shown in the example above.(e.g. CXX_c2)"
    append_uservars "#CXX=powerpc-440-linux-gnu-g++"
    append_uservars "#AR=powerpc-440-linux-gnu-ar"
    append_uservars ""
    append_uservars ""
    append_uservars "# Files that are generated based on the uservars.Makefile"
    append_uservars "# You can change the name of these files in case you have"
    append_uservars "# something in your project that conflicts with these files"
    append_uservars "VARSFILE=.vars"
    append_uservars "RULESFILE=.rules"
    append_uservars "#preALL="
    append_uservars "#postALL="
    append_uservars "#preCLEAN="
    append_uservars "#postCLEAN="

    begin_lookupmake  "#Utilities.. Do not modify me unless you know what you're doing"
    append_lookupmake "#Generated by ${WHOAMI} at ${DATENOW} with curry-${VERSION_CURRY}"
    append_lookupmake "include ${USERVARSMAKEFILE}"
    append_lookupmake "ALLSOURCES=\$(foreach comp,\$(COMPOSITES),\$(SOURCES_\$(comp)))"
    append_lookupmake "ALLTARGETS=\$(foreach comp,\$(COMPOSITES),\$(DLIB_\$(comp)) \$(SLIB_\$(comp)) \$(EXEC_\$(comp)))"
    append_lookupmake "ALLTARGETS_TARGET=\$(foreach target,\$(ALLTARGETS),\$(target)_target)"
    append_lookupmake ""
    append_lookupmake "lookupvar:"
    append_lookupmake "\t@echo \"\$(\$(V))\""
    append_lookupmake "lookupvars:"
    append_lookupmake "\t@echo \$(foreach var, \$(V),\$(var)=\\\"\$(\$(var))\\\")"
    append_lookupmake ""
    append_lookupmake "RULESFILE_SAFE=\$(shell if [ ! -z \$(RULESFILE) ]; then\\"
    append_lookupmake "INC=0; \\"
    append_lookupmake "while [ -f \$(RULESFILE).\$\${INC} ]; do \\"
    append_lookupmake "INC=\$\$((INC=INC+1)) ;\\"
    append_lookupmake "done ;\\"
    append_lookupmake "echo \$(RULESFILE).\$\${INC} ;\\"
    append_lookupmake "else\\"
    append_lookupmake "echo \"RULESFILE not defined in uservars.Makefile\";\\"
    append_lookupmake "fi ;\\"
    append_lookupmake ")"
    append_lookupmake "VARSFILE_SAFE=\$(shell if [ ! -z \$(VARSFILE) ]; then\\"
    append_lookupmake "INC=0; \\"
    append_lookupmake "while [ -f \$(VARSFILE).\$\${INC} ]; do \\"
    append_lookupmake "INC=\$\$((INC=INC+1)) ;\\"
    append_lookupmake "done ;\\"
    append_lookupmake "echo \$(VARSFILE).\$\${INC} ;\\"
    append_lookupmake "else\\"
    append_lookupmake "echo \"VARSFILE not defined in uservars.Makefile\";\\"
    append_lookupmake "fi ;\\"
    append_lookupmake ")"
    append_lookupmake "CURRY=\$(shell which curry)"
    append_lookupmake "config: \$(RULESFILE) \$(VARSFILE)"
    append_lookupmake "\t@echo \"curry, \$@, done\""
    append_lookupmake "\$(RULESFILE): ${USERVARSMAKEFILE}"
    append_lookupmake "ifeq (\$(CURRY),)"
    append_lookupmake "\t@echo \"WARNING:  curry not available, avoiding regneration.  Structural updates to\""
    append_lookupmake "\t@echo \"WARNING:  \\\"uservars.Makefile\\\" will not be applied.\""
    append_lookupmake "else"
    append_lookupmake "\t@echo \"Creating rules file(\$(RULESFILE))\""
    append_lookupmake "\tcurry -rules \$(COMPOSITES) > \$(RULESFILE_SAFE)"
    append_lookupmake "\tif [ \$\$? -eq 0 ]; then mv \$(RULESFILE_SAFE) \$(RULESFILE); else echo \"curry failed, maybe try curry -reinit\"; fi"
    append_lookupmake "endif"
    append_lookupmake "\$(VARSFILE): ${USERVARSMAKEFILE}"
    append_lookupmake "ifeq (\$(CURRY),)"
    append_lookupmake "\t@echo \"WARNING:  curry not available, avoiding regneration.  Structural updates to\""
    append_lookupmake "\t@echo \"WARNING:  \\\"uservars.Makefile\\\" will not be applied.\""
    append_lookupmake "else"
    append_lookupmake "\t@echo \"Creating vars file(\$(VARSFILE))\""
    append_lookupmake "\tcurry -vars \$(COMPOSITES) > \$(VARSFILE_SAFE)"
    append_lookupmake "\tif [ \$\$? -eq 0 ]; then mv \$(VARSFILE_SAFE) \$(VARSFILE); else echo \"curry failed, maybe try curry -reinit\"; fi"
    append_lookupmake "endif"
    append_lookupmake "testsrcs:"
    append_lookupmake "\t(for i in \$(ALLSOURCES); do \\"
    append_lookupmake "        if [ ! -f \$\$i ]; then \\"
    append_lookupmake "        echo \"ERROR [File Not found]:  \$\$i\";\\"
    append_lookupmake "        exit 1;\\"
    append_lookupmake "        fi done)"
    append_lookupmake ""








    begin_utilsmake  "#Utilities.. Do not modify me unless you know what you're doing"
    append_utilsmake "#Generated by ${WHOAMI} at ${DATENOW} with curry-${VERSION_CURRY}"
    append_utilsmake "SHELL=/bin/bash"
    append_utilsmake "include ${USERVARSMAKEFILE}"
    append_utilsmake "include \$(VARSFILE)"
    append_utilsmake "ALLSOURCES=\$(foreach comp,\$(COMPOSITES),\$(SOURCES_\$(comp)))"
    append_utilsmake "ALLOBJDIR=\$(foreach comp,\$(COMPOSITES),\$(OBJDIR_\$(comp)))"
    append_utilsmake "ALLTARGETS=\$(foreach comp,\$(COMPOSITES),\$(DLIB_\$(comp)) \$(SLIB_\$(comp)) \$(EXEC_\$(comp)))"
    append_utilsmake "ALLDEPS=\$(foreach comp,\$(COMPOSITES),\$(DEPS_\$(comp)))"
    append_utilsmake ""
    append_utilsmake "OS_DETECT=\$(shell uname)"
    append_utilsmake "ifeq (\$(LDFLAGS_\$(E)),)"
    append_utilsmake "ifeq (\$(OS_DETECT),Darwin)"
    append_utilsmake "GENLDLIBRARY:=\$(shell echo \"\$(LDFLAGS_default)\" | sed -e 's/\ *-l[^ ]*//g' -e 's/[ \t][ \t]*/\ /g' -e 's/-L/:/g' -e 's/\ //g' -e 's/\(.*\)/DYLD_LIBRARY_PATH=\$\${DYLD_LIBRARY_PATH}\1/')"
    append_utilsmake "else"
    append_utilsmake "GENLDLIBRARY:=\$(shell echo \"\$(LDFLAGS_default)\" | sed -e 's/\ *-l[^ ]*//g' -e 's/[ \t][ \t]*/\ /g' -e 's/-L/:/g' -e 's/\ //g' -e 's/\(.*\)/LD_LIBRARY_PATH=\$\${LD_LIBRARY_PATH}\1/')"
    append_utilsmake "endif"
    append_utilsmake "else"
    append_utilsmake "ifeq (\$(OS_DETECT),Darwin)"
    append_utilsmake "GENLDLIBRARY:=\$(shell echo \"\$(LDFLAGS_\$(E))\" | sed -e 's/\ *-l[^ ]*//g' -e 's/[ \t][ \t]*/\ /g' -e 's/-L/:/g' -e 's/\ //g' -e 's/\(.*\)/DYLD_LIBRARY_PATH=\$\${DYLD_LIBRARY_PATH}\1/')"
    append_utilsmake "else"
    append_utilsmake "GENLDLIBRARY:=\$(shell echo \"\$(LDFLAGS_\$(E))\" | sed -e 's/\ *-l[^ ]*//g' -e 's/[ \t][ \t]*/\ /g' -e 's/-L/:/g' -e 's/\ //g' -e 's/\(.*\)/LD_LIBRARY_PATH=\$\${LD_LIBRARY_PATH}\1/')"
    append_utilsmake "endif"
    append_utilsmake "endif"
    append_utilsmake "run: check_existence_of_composite  check_if_executable_exists"
    append_utilsmake "\t@echo -e \"\\\n\\\n\""
    append_utilsmake "ifneq (\$(A),)"
    append_utilsmake "\t\$(GENLDLIBRARY) ./\$(EXEC_\$(E)) \$(A)"
    append_utilsmake "else"
    append_utilsmake " ifneq (\$(A_\$(E)),)"
    append_utilsmake "\t\$(GENLDLIBRARY) ./\$(EXEC_\$(E)) \$(A_\$(E))"
    append_utilsmake " else"
    append_utilsmake "\t\$(GENLDLIBRARY) ./\$(EXEC_\$(E)) \$(A_default)"
    append_utilsmake " endif"
    append_utilsmake "endif"
    append_utilsmake "\t@echo -e \"\\\n\\\n\""
    append_utilsmake ""
    append_utilsmake "check_existence_of_composite:"
    append_utilsmake "ifeq (\$(E),)"
    append_utilsmake "\t@(echo -e \"\\\n\\\nE= not defined, or empty.\\\n\\\n\"; exit 1;)"
    append_utilsmake "else"
    append_utilsmake "\t@(echo \$(COMPOSITES) | grep -w \$(E) > /dev/null ; if [ \$\$? -ne 0 ]; then \\"
    append_utilsmake "echo -e \"\\\n\\\nERROR [Composite not found]: \$(E)\";\\"
    append_utilsmake "echo -e \"Possible options are: \$(COMPOSITES)\\\n\\\n\"; \\"
    append_utilsmake "exit 1;\\"
    append_utilsmake "fi)"
    append_utilsmake "endif"
    append_utilsmake ""
    append_utilsmake "check_if_executable_exists:"
    append_utilsmake "\t@( if [ ! -f \$(EXEC_\$(E)) ]; then \\"
    append_utilsmake "echo -e \"\\\n\\\nERROR [Executable does not exist]: \$(EXEC_\$(E))\"; \\"
    append_utilsmake "echo -e \"Try running 'make'\\\n\\\n\";\\"
    append_utilsmake "exit 1;\\"
    append_utilsmake "fi)"
    append_utilsmake ""
    append_utilsmake "lookuputilsvar:"
    append_utilsmake "\t@echo \"\$(\$(V))\""
    append_utilsmake "lookuputilsvars:"
    append_utilsmake "\t@echo \$(foreach var, \$(V),\$(var)=\\\"\$(\$(var))\\\")"
    append_utilsmake "clean: \$(preCLEAN) curryclean \$(postCLEAN)"
    append_utilsmake "\t@echo \"\$@, Done\""
    append_utilsmake "curryclean:"
    append_utilsmake "ifneq (\$(ALLOBJDIR),)"
    append_utilsmake "\trm -Rf \$(ALLOBJDIR)"
    append_utilsmake "endif"
    append_utilsmake "ifneq (\$(ALLTARGETS),)"
    append_utilsmake "\trm -f \$(ALLTARGETS)"
    append_utilsmake "endif"
    append_utilsmake "ifneq (\$(ALLDEPS),)"
    append_utilsmake "\trm -f \$(ALLDEPS)"
    append_utilsmake "endif"
    append_utilsmake "\t(for i in \$(ALLSOURCES); do \\"
    append_utilsmake "        if [ -f \$\${i}~ ]; then \\"
    append_utilsmake "        rm \$\${i}~;\\"
    append_utilsmake "        fi done)"


    begin_coremake "#Core GUTS...Do not modify me unless you know what you're doing "
    append_coremake "#Generated by ${WHOAMI} at ${DATENOW} with curry-${VERSION_CURRY}"
    append_coremake "include ${USERVARSMAKEFILE}"
    append_coremake "ALLTARGETS=\$(foreach comp,\$(COMPOSITES),\$(DLIB_\$(comp)) \$(SLIB_\$(comp)) \$(EXEC_\$(comp)))"
    append_coremake "ALLTARGETS_LIBS=\$(foreach comp,\$(COMPOSITES),\$(DLIB_\$(comp)) \$(SLIB_\$(comp)))"
    append_coremake "ALLOBJDIR=\$(foreach comp,\$(COMPOSITES),\$(OBJDIR_\$(comp)))"
    append_coremake "ALLDEPS=\$(foreach comp,\$(COMPOSITES),\$(DEPS_\$(comp)))"
    append_coremake "ALLSOURCES=\$(foreach comp,\$(COMPOSITES),\$(SOURCES_\$(comp)))"
    append_coremake "ALLTARGETS_TARGET=\$(foreach target,\$(ALLTARGETS),\$(target)_target)"
    append_coremake "ALLOBJDIR=\$(foreach comp,\$(COMPOSITES),\$(OBJDIR_\$(comp)))"
    append_coremake "-include \$(VARSFILE)"
    append_coremake "all: \$(preALL) target \$(postALL)"
    append_coremake "\t@echo \"\$@, Done\""
    append_coremake "target: \$(ALLOUTPUTDIRS) \$(ALLTARGETS_TARGET)"
    append_coremake ""
    append_coremake "-include \$(RULESFILE)"
    append_coremake "lookupgenvar:"
    append_coremake "\t@echo \"\$(\$(V))\""
    append_coremake "lookupgenvars:"
    append_coremake "\t@echo \$(foreach var, \$(V),\$(var)=\\\"\$(\$(var))\\\")"
    append_coremake ""


    begin_mainmake "#NO NEED TO MODIFY THIS FILE"
    append_mainmake "#  Please Modify \"uservars.Makefile\" instead of this file"
    append_mainmake "#Generated by ${WHOAMI} at ${DATENOW} with curry-${VERSION_CURRY}"
    append_mainmake "UTILSMAKEFILE=${UTILSMAKEFILE}"
    append_mainmake "COREMAKEFILE=${COREMAKEFILE}"
    append_mainmake "LOOKUPMAKEFILE=${LOOKUPMAKEFILE}"
    append_mainmake ""
    append_mainmake "#SUPPRESSFLAGS is used incase the -w flag was used (or -C, which implictly"
    append_mainmake "#              turns on -w)"
    append_mainmake "ifneq (\$(MAKEFLAGS),)"
    append_mainmake "SUPPRESSFLAGS=\$(shell echo \"\$(MAKEFLAGS)\" | grep \"w\" > /dev/null;\\"
    append_mainmake "if [ \$\$? -eq 0 ]; then \\"
    append_mainmake "echo \"--no-print-directory\";\\"
    append_mainmake "fi)"
    append_mainmake "endif"
    append_mainmake ""
    append_mainmake "CURRYWORKDIR=\$(dir \$(firstword \$(MAKEFILE_LIST)))"
    append_mainmake ""
    append_mainmake "all:testsrcs config"
    append_mainmake "\t@cd \$(CURRYWORKDIR) && make \$(SUPPRESSFLAGS) -f \$(COREMAKEFILE) \$@"
    append_mainmake "config:"
    append_mainmake "\t@cd \$(CURRYWORKDIR) && make \$(SUPPRESSFLAGS) -s -f \$(LOOKUPMAKEFILE) \$@"
    append_mainmake ""
    append_mainmake "clean:"
    append_mainmake "\t@cd \$(CURRYWORKDIR) && make  -f \$(UTILSMAKEFILE) \$@"
    append_mainmake ""
    append_mainmake "#Example:    ' make run E=main'"
    append_mainmake "run:"
    append_mainmake "\t@cd \$(CURRYWORKDIR) && make \$(SUPPRESSFLAGS) -f \$(UTILSMAKEFILE) \$@"
    append_mainmake ""
    append_mainmake "testsrcs:"
    append_mainmake "\t@cd \$(CURRYWORKDIR) && make \$(SUPPRESSFLAGS) -s -f \$(LOOKUPMAKEFILE) \$@"
    append_mainmake ""
    append_mainmake "lookupvar:"
    append_mainmake "\t@cd \$(CURRYWORKDIR) && make \$(SUPPRESSFLAGS) -s -f \$(LOOKUPMAKEFILE) \$@ V=\$(V)"
    append_mainmake "lookupvars:"
    append_mainmake "\t@cd \$(CURRYWORKDIR) && make \$(SUPPRESSFLAGS) -s -f \$(LOOKUPMAKEFILE) \$@ V=\$(V)"
    append_mainmake "lookupgenvar:"
    append_mainmake "\t@cd \$(CURRYWORKDIR) && make \$(SUPPRESSFLAGS) -s -f \$(COREMAKEFILE) \$@ V=\$(V)"
    append_mainmake "lookupgenvars:"
    append_mainmake "\t@cd \$(CURRYWORKDIR) && make \$(SUPPRESSFLAGS) -s -f \$(COREMAKEFILE) \$@ V=\$(V)"
    append_mainmake "lookuputilsvar:"
    append_mainmake "\t@cd \$(CURRYWORKDIR) && make \$(SUPPRESSFLAGS) -s -f \$(UTILSMAKEFILE) \$@ V=\$(V)"
    append_mainmake "lookuputilsvars:"
    append_mainmake "\t@cd \$(CURRYWORKDIR) && make \$(SUPPRESSFLAGS) -s -f \$(UTILSMAKEFILE) \$@ V=\$(V)"



    echo "Done!"
}

if [ $INIT -eq 1 ]; then
    doCURRY_INIT
fi
if [ $DESTROY -eq 1 ]; then
    doCURRY_DESTROY
fi

if [ $REINIT -eq 1 ]; then
    if [ -f ${USERVARSMAKEFILE} ]; then
	INC=0
	while [ -f ${USERVARSMAKEFILE}.${INC} ]; do
	   INC=$((INC=INC+1))
	done
	BACKUPFILE=${USERVARSMAKEFILE}.${INC}
	echo "Backing up ${USERVARSMAKEFILE}..."
	cp -vf ${USERVARSMAKEFILE} ${BACKUPFILE}
	echo ""
	doCURRY_DESTROY
	doCURRY_INIT
	echo "Restoring ${USERVARSMAKEFILE}..."
	cp -vf ${BACKUPFILE} ${USERVARSMAKEFILE}
	if [ $? -eq 0 ]; then
	    rm -f ${BACKUPFILE}
	fi
	echo ""
    else
	echo "No need for reinit, ${USERVARSMAKEFILE} does not exist"
    fi

fi

if [ $VERSION -eq 1 ]; then
    echo -n "curry-${VERSION_CURRY}"
fi



echo ""
